package com.fxpc.hddc.service;

import com.alibaba.fastjson.JSON;
import com.fxpc.common.FxpcScheduleConstant;
import com.fxpc.common.TaskInfoEnum;
import com.fxpc.common.vo.ScheduleInfoVo;
import com.fxpc.common.vo.SendDataRes;
import com.fxpc.config.MyX509TrustManager;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @Author Zyl
 * @Date 2021/4/14 9:40
 * @Version 1.0
 * @Describe: 全国自然灾害综合风险普查系统 地震行业数据进度发送
 */
@Service
public class ManagerService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private String taskTypeQt=FxpcScheduleConstant.EQ_TYPE_QT;
    private String taskTypeRp=FxpcScheduleConstant.EQ_TYPE_RP;
    @Autowired
    ServiceLocator serviceLocator;

    /**
     * 质检任务进度发送
     *
     * @return
     */
    @Scheduled(cron = "${schedule.cron}")
    public void eqTaskProgressQtSend() {
        logger.info("##########################   质检进度发送  start");
        Map<String, EqScheduleBaseService> map = serviceLocator.getMap();
        Map<String, List<ScheduleInfoVo>> allQtScheduleInfo = new HashMap<>();
        for (String service : map.keySet()) {
            EqScheduleBaseService eqScheduleBaseService = map.get(service);
            Map<String, List<ScheduleInfoVo>> taskInfoMap = eqScheduleBaseService.qualityTaskProgressCollection();
            if (taskInfoMap != null) {
                allQtScheduleInfo.putAll(taskInfoMap);
                List<ScheduleInfoVo> scheduleInfoList = null;
                String taskName = "";
                for (String name : taskInfoMap.keySet()) {
                    scheduleInfoList = taskInfoMap.get(name);
                    taskName = name;
                }
                SendDataRes sendDataRes = new SendDataRes();
                sendDataRes.setDataTime(LocalDateTime.now());
                sendDataRes.setDepType(FxpcScheduleConstant.DEPTYPE_9);
                sendDataRes.setTaskType(FxpcScheduleConstant.TASKTYPE_3);
                sendDataRes.setData(getCountryScheduleInfo(scheduleInfoList));
                httpsSendCommonMethod(taskName, TaskInfoEnum.getInstanceByName(taskName).getTaskCode(), taskTypeQt, sendDataRes);
            }else {
                logger.info("++++++++质检接口实现类为空,实现类名:【{}】",service);
            }
        }
        //9 质检
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9").getTaskName(), "9", taskTypeQt, combinationData(allQtScheduleInfo, "9", taskTypeQt));
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9-91").getTaskName(), "9-91", taskTypeQt, combinationData(allQtScheduleInfo, "9-91", taskTypeQt));
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9-92").getTaskName(), "9-92", taskTypeQt, combinationData(allQtScheduleInfo, "9-92", taskTypeQt));
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9-93").getTaskName(), "9-93", taskTypeQt, combinationData(allQtScheduleInfo, "9-93", taskTypeQt));
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9-94").getTaskName(), "9-94", taskTypeQt, combinationData(allQtScheduleInfo, "9-94", taskTypeQt));
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9-95").getTaskName(), "9-95", taskTypeQt, combinationData(allQtScheduleInfo, "9-95", taskTypeQt));
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9-96").getTaskName(), "9-96", taskTypeQt, combinationData(allQtScheduleInfo, "9-96", taskTypeQt));
        logger.info("##########################   质检进度发送结束");
        System.out.println(" ");
        System.out.println(" ");
        System.out.println(" ");
//        try {
//            Thread.sleep(20000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
    }

    /**
     * 上报任务进度发送
     *
     * @return
     */
    @Scheduled(cron = "${schedule.cron}")
    public void eqTaskProgressRpSend() {
        logger.info("##########################   上报进度发送  start");
        Map<String, EqScheduleBaseService> map = serviceLocator.getMap();
        //所有任务的进度集合合并
        Map<String, List<ScheduleInfoVo>> allRpScheduleInfo = new HashMap<>();
        for (String service : map.keySet()) {
            EqScheduleBaseService eqScheduleBaseService = map.get(service);
            //掉用实现类获取数据
            Map<String, List<ScheduleInfoVo>> taskInfoMap = eqScheduleBaseService.reportTaskProgressCollection();
            if (taskInfoMap != null) {
                allRpScheduleInfo.putAll(taskInfoMap);
                List<ScheduleInfoVo> scheduleInfoList = null;
                String taskName = "";
                for (String name : taskInfoMap.keySet()) {
                    scheduleInfoList = taskInfoMap.get(name);
                    taskName = name;
                }
                SendDataRes sendDataRes = new SendDataRes();
                sendDataRes.setDataTime(LocalDateTime.now());
                sendDataRes.setDepType(FxpcScheduleConstant.DEPTYPE_9);
                sendDataRes.setTaskType(FxpcScheduleConstant.TASKTYPE_4);
                sendDataRes.setData(getCountryScheduleInfo(scheduleInfoList));
                //单个任务上报任务发送
                httpsSendCommonMethod(taskName, TaskInfoEnum.getInstanceByName(taskName).getTaskCode(), taskTypeRp, sendDataRes);
            }else{
                logger.info("++++++++上报接口实现类为空,实现类名:【{}】",service);
            }
        }
        //9 全国 上报
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9").getTaskName(), "9", taskTypeRp, combinationData(allRpScheduleInfo, "9", taskTypeRp));
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9-91").getTaskName(), "9-91", taskTypeRp, combinationData(allRpScheduleInfo, "9-91", taskTypeRp));
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9-92").getTaskName(), "9-92", taskTypeRp, combinationData(allRpScheduleInfo, "9-92", taskTypeRp));
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9-93").getTaskName(), "9-93", taskTypeRp, combinationData(allRpScheduleInfo, "9-93", taskTypeRp));
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9-94").getTaskName(), "9-94", taskTypeRp, combinationData(allRpScheduleInfo, "9-94", taskTypeRp));
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9-95").getTaskName(), "9-95", taskTypeRp, combinationData(allRpScheduleInfo, "9-95", taskTypeRp));
        httpsSendCommonMethod(TaskInfoEnum.getInstanceByCode("9-96").getTaskName(), "9-96", taskTypeRp, combinationData(allRpScheduleInfo, "9-96", taskTypeRp));
        logger.info("##########################   上报进度发送结束");
        System.out.println(" ");
        System.out.println(" ");
        System.out.println(" ");

    }

    //获取国家的进度(所有省市县数量相加)
    public Collection<ScheduleInfoVo> getCountryScheduleInfo(Collection<ScheduleInfoVo> scheduleInfoList) {
        Integer allCountSum = 0;
        Integer finshCountSum = 0;
        String id = "";
        for (ScheduleInfoVo scheduleInfo : scheduleInfoList) {
            if(StringUtils.isEmpty(scheduleInfo.getCode())){
                logger.warn("++++++区划编码为空【{}】",scheduleInfo.getId());
            }
            if(scheduleInfo.getAllCount()==0){
                logger.warn("++++++进度总数据AllCount为空【{}】,信息【{}】",scheduleInfo.getId(),scheduleInfo);
            }
            //当区划是省时将数据相加
            if(scheduleInfo.getCode().length()==2){
                allCountSum += scheduleInfo.getAllCount();
                finshCountSum += scheduleInfo.getFinishCount();
            }
            id = scheduleInfo.getId();
        }
        float percent = (float) finshCountSum / allCountSum;
        if(finshCountSum>allCountSum){
            System.out.println("数据超过100%");
            percent=1;
        }
        scheduleInfoList.add(new ScheduleInfoVo(id, "0", allCountSum, finshCountSum, percent));
        return scheduleInfoList;
    }


    /**
     * 组合父级任务数据工具
     */
    public SendDataRes combinationData(Map<String, List<ScheduleInfoVo>> taskInfoMap, String taskCode, String type) {
        //拿到父级任务编码对应的所有子任务，然后相同区划下的数量相加
        List<ScheduleInfoVo> allScheduleInfoList = new ArrayList<>();
        for (String taskName : taskInfoMap.keySet()) {
            //子任务编码
            String subTaskCode = TaskInfoEnum.getInstanceByName(taskName).getTaskCode();
            if (subTaskCode.contains(taskCode)) {
                allScheduleInfoList.addAll(taskInfoMap.get(taskName));
            }
        }
        //相同区划下的数量相加
        if (!CollectionUtils.isEmpty(allScheduleInfoList)) {
            Map<String, ScheduleInfoVo> scheduleInfoMap = new HashMap<>();
            int taskStatu = 0;
            for (ScheduleInfoVo scheduleInfo : allScheduleInfoList) {
                String code = scheduleInfo.getCode();//key
                ScheduleInfoVo value = scheduleInfoMap.get(code);//value
                if (value == null) {
                    if (taskTypeQt.equals(type)) {
                        taskStatu = FxpcScheduleConstant.TASKTYPE_3;
                        scheduleInfo.setId(TaskInfoEnum.getInstanceByCode(taskCode).getQtId());
                    } else {
                        taskStatu = FxpcScheduleConstant.TASKTYPE_4;
                        scheduleInfo.setId(TaskInfoEnum.getInstanceByCode(taskCode).getRpId());
                    }
                    scheduleInfoMap.put(code, scheduleInfo);
                } else {//重复
                    ScheduleInfoVo supScheduleInfo = new ScheduleInfoVo();
                    Integer allCount = scheduleInfo.getAllCount() + value.getAllCount();
                    Integer finshCount = scheduleInfo.getFinishCount() + value.getFinishCount();
                    supScheduleInfo.setAllCount(allCount);
                    supScheduleInfo.setFinishCount(finshCount);
                    supScheduleInfo.setCode(code);
                    float percent = (float) finshCount / allCount;
                    if(finshCount>allCount){
                        System.out.println("数据超过100%");
                        percent=1;
                    }
                    supScheduleInfo.setPercent(percent);
                    supScheduleInfo.setId(value.getId());
                    scheduleInfoMap.put(code, supScheduleInfo);
                }
            }
            SendDataRes sendDataRes = new SendDataRes();
            sendDataRes.setDataTime(LocalDateTime.now());
            sendDataRes.setDepType(FxpcScheduleConstant.DEPTYPE_9);
            sendDataRes.setTaskType(taskStatu);
            sendDataRes.setData(scheduleInfoMap.values());
            return sendDataRes;
        } else {
            return null;
        }
    }

    /**
     * @param taskName 任务名称
     * @param sendData 发送的数据
     * @param type     任务类型 ：质检-上报
     */
    public void httpsSendCommonMethod(String taskName, String taskCode, String type, SendDataRes sendData) {
        if (sendData != null) {
            String postData = JSON.toJSONString(sendData);
            logger.info("==========" + taskCode + taskName + " " + type + ",发送数据为【{}】", postData);
            //String url = "http://ddglyh.geo-compass.com/task_back/api/v1/task_inital/jindu_gather";
            String url = "https://fxpc.mem.gov.cn/task_back/api/v1/task_inital/jindu_gather";
            HttpURLConnection conn = null;
            try {
                byte[] byteArray = postData.getBytes("utf-8");
                //忽略证书
                SSLContext sslcontext = SSLContext.getInstance("SSL", "SunJSSE");
                sslcontext.init(null, new TrustManager[]{new MyX509TrustManager()}, new java.security.SecureRandom());
                URL serverUrl = new URL(url);
                //忽略
                HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {
                    public boolean verify(String s, SSLSession sslsession) {
                        //System.out.println("WARNING: Hostname is not matched for cert.");
                        return true;
                    }
                };
                HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier);
                HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
                conn = (HttpURLConnection) serverUrl.openConnection();
                conn.setRequestMethod("POST");
                conn.setRequestProperty("token", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkZXBUeXBlIjo5LCJrZXkiOiJneHNuXzVaeXc2WnlIOSIsImlhdCI6MTYxNzE1NzgxNn0.dkb4tqvCmexrLLZUd1nOiwfV_fKTdQFjHCYWkTreatQ");
                conn.setRequestProperty("Content-Type", "application/json");
                //必须设置false，否则会自动redirect到重定向后的地址
                conn.setInstanceFollowRedirects(false);
                //设置参数
                conn.setDoInput(true);
                conn.setDoOutput(true);
                OutputStream out = conn.getOutputStream();
                out.write(byteArray);
                out.close();
                conn.connect();
                String result = getReturn(conn);
                logger.info("==========" + taskName + " " + type + ",接收结果为:【{}】", result);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /*请求url获取返回的内容*/
    public static String getReturn(HttpURLConnection connection) throws IOException {
        StringBuffer buffer = new StringBuffer();
        //将返回的输入流转换成字符串
        try (InputStream inputStream = connection.getInputStream();
             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);) {
            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            String result = buffer.toString();
            return result;
        }
    }
}
